package xjf.learn.lambda;

import org.junit.Test;
import xjf.base.entity.Employee;
import xjf.base.support.FilterEmployeeByAge;
import xjf.base.support.FilterEmployeeBySalary;
import xjf.base.support.MyPredicate;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 进行优化
 *
 * @Author: xjf
 * @Date: 2020/4/9 21:57
 */
public class Test3 {

    /**
     * 数据准备
     */
    private List<Employee> employeeList = Arrays.asList(
            new Employee("张三", 45, 6000),
            new Employee("李四", 20, 7600),
            new Employee("王五", 38, 4900),
            new Employee("赵六", 77, 2000),
            new Employee("田七", 54, 6500)
    );

    /**
     * 优化方式一：设计模式-策略模式。
     * <p>
     * 优点：将条件判断提取出来，便于扩展。
     * 缺点：每新加条件都要写一个 MyPredicate 的实现类
     */
    @Test
    public void test1() {
        // 根据年龄过滤
        List<Employee> resultList = filterEmployee(employeeList, new FilterEmployeeByAge());

        for (Employee employee : resultList) {
            System.out.println(employee);
        }

        System.out.println("==================================================================================");

        // 根据工资过滤
        List<Employee> resultList2 = filterEmployee(employeeList, new FilterEmployeeBySalary());

        for (Employee employee : resultList2) {
            System.out.println(employee);
        }
    }

    /**
     * 优化方式二：匿名内部类
     * <p>
     * 优点：不需要像策略模式一样换判断依据就要加类，要什么条件不需要手动添加新类。可以直接用的时候动态实现
     * 缺点：匿名内部类的共通的缺点，支持代码太多，实际生效代码此处就一句。
     */
    @Test
    public void test2() {
        // 按年龄过滤
        List<Employee> resultList = filterEmployee(employeeList, new MyPredicate<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getAge() >= 35;
            }
        });

        for (Employee employee : resultList) {
            System.out.println(employee);
        }

        System.out.println("==================================================================================");

        // 按工资过滤
        List<Employee> resultList2 = filterEmployee(employeeList, new MyPredicate<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getSalary() >= 5000;
            }
        });

        for (Employee employee : resultList2) {
            System.out.println(employee);
        }
    }

    /**
     * 优化方式三：Lambda 表达式
     * <p>
     * 优点：代码简洁，易懂
     * 缺点：我们需要手动实现一个过滤方法 filterEmployee
     */
    @Test
    public void test3() {
        // 根据年龄过滤
        List<Employee> resultList = filterEmployee(employeeList, (employee) -> employee.getAge() >= 35);
        resultList.forEach(System.out::println);

        System.out.println("==================================================================================");

        // 根据工资过滤
        List<Employee> resultList2 = filterEmployee(employeeList, (employee -> employee.getSalary() >= 5000));
        resultList2.forEach(System.out::println);
    }

    /**
     * 过滤方法
     */
    private List<Employee> filterEmployee(List<Employee> inputList, MyPredicate<Employee> mp) {
        List<Employee> tempList = new ArrayList<>();

        for (Employee employee : inputList) {
            if (mp.test(employee)) {
                tempList.add(employee);
            }
        }

        return tempList;
    }



    /*============================================= 大家觉得还能再简洁吗？========================================*/











































    /**
     * 优化方式四：Stream API
     *
     * 优点：是否简洁，同时支持多种操作
     * 缺点: 一开始不习惯看这种类型的代码，感觉难以理解
     */
    @Test
    public void test4() {
        // 根据年龄过滤
        employeeList.stream()
                .filter(employee -> employee.getAge() >= 35)
                .forEach(System.out::println);

        System.out.println("==================================================================================");

        // 根据工资过滤
        employeeList.stream()
                .filter(employee -> employee.getSalary() >= 5000)
                .forEach(System.out::println);

        // 测试 idea 调试
        /*employeeList.stream()
                .filter(employee -> employee.getAge() >= 35)
                .map(Employee::getName)
                .count();*/

    }


}
